#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import sys

from common.common import exter_attack, output_result_file
from common.const import SysData
from common.logger import Logger
from common.parse_parafile import ParamFileUtil
from db2.comm.constant import DB2Type
from db2.comm.error_code import Db2ErrCode, DB2Code
from db2.comm.param_parse import Param
from db2.resource.check_instance import Instance
from db2.resource.check_table_space import TableSpaces
from db2.resource.query_cluster import QueryCluster
from db2.resource.query_datasize import DataBaseSizeInfo
from db2.resource.scan_database import DatabaseInformation

LOGGER = Logger().get_logger(filename="db2.log")


class DB2Resource:

    def __init__(self, pid, param_obj: Param):
        self.pid = pid
        self.param = param_obj

    @exter_attack
    def check_application(self):
        """
        check the user name(authKey) is the same as database user name
        """
        resource_type = self.param.sub_type
        cluster = Instance(self.pid, self.param)
        if resource_type in (DB2Type.DB2INSTANCE, DB2Type.DB2CLUSTERINSTANCE):
            return cluster.check_db2_message(resource_type)
        error_message = "This type is not allowed !"
        params = Param.get_body_error_param(DB2Code.FAILED.value, Db2ErrCode.ERROR_COMMON_INVALID_PARAMETER,
                                            error_message)

        LOGGER.error(error_message)
        return params

    @exter_attack
    def list_application_resource(self):
        """
        获取资源列表
        """
        resource_type = self.param.sub_type
        if resource_type == DB2Type.DB2INSTANCE:
            return DatabaseInformation(self.pid, self.param).get_databases()
        elif resource_type == DB2Type.DB2TABLESPACE:
            return TableSpaces(self.pid, self.param).list_for_tablespaces()
        else:
            return DataBaseSizeInfo(self.pid, self.param).datasize_for_databases()

    @exter_attack
    def query_cluster(self):
        """
        查询主备
        """
        return QueryCluster(self.pid, self.param).query_cluster_ha()


@exter_attack
def run():
    if len(sys.argv) < 3:
        LOGGER.error("Number of argv wrong. ")
        return Db2ErrCode.ERROR_COMMON_INVALID_PARAMETER
    func_type = sys.argv[1]
    pid = sys.argv[2]
    try:
        parm_cont_dict = ParamFileUtil.parse_param_file(pid)
    except Exception as ex:
        LOGGER.error(f"Parse param file failed,{ex}.")
        return Db2ErrCode.ERROR_COMMON_INVALID_PARAMETER
    if not parm_cont_dict:
        LOGGER.error("Param is none.")
        return Db2ErrCode.ERROR_COMMON_INVALID_PARAMETER

    if func_type not in ("CheckApplication", "QueryCluster", "ListApplicationResource"):
        LOGGER.error("Unknown command from command line!")
        return Db2ErrCode.ERROR_COMMON_INVALID_PARAMETER

    param = Param(parm_cont_dict, pid)
    resource = DB2Resource(pid, param)
    execute_func = {
        "CheckApplication": resource.check_application,
        "ListApplicationResource": resource.list_application_resource,
        "QueryCluster": resource.query_cluster
    }
    res_exec = execute_func.get(func_type)
    try:
        output = res_exec()
    except Exception as ex:
        LOGGER.exception(f"Execute cmd {func_type} with exception.")
        return Db2ErrCode.OPERATION_FAILED
    try:
        output_result_file(pid, output)
    except Exception as ex:
        LOGGER.error("Write result failed with error")
        return Db2ErrCode.OPERATION_FAILED
    return DB2Code.SUCCESS.value


if __name__ == '__main__':
    for line in sys.stdin:
        SysData.SYS_STDIN = line
        break
    sys.exit(run())
